package cn.wen.rpc.netty.codec;

import cn.wen.rpc.compress.Compress;
import cn.wen.rpc.constant.WenRpcConstants;
import cn.wen.rpc.message.WenMessage;
import cn.wen.rpc.serialize.ProtostuffSerializer;
import cn.wen.rpc.serialize.Serializer;
import cn.wen.rpc.utils.SPIUtils;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;

import java.util.concurrent.atomic.AtomicInteger;

public class WenRpcEncoder extends MessageToByteEncoder<WenMessage> {

    private static final AtomicInteger ATOMIC_INTEGER = new AtomicInteger(0);

    // 1. 4B  magic code（魔法数）
    // 2. 1B version（版本）
    // 3. 4B full length（消息长度）
    // 4. 1B messageType（消息类型）
    // 5. 1B codec（序列化类型）
    // 6. 1B compress（压缩类型）
    // 7. 4B  requestId（请求的Id）
    // 8. body（object类型数据）
    @Override
    protected void encode(ChannelHandlerContext channelHandlerContext,
                          WenMessage wenMessage,
                          ByteBuf out) throws Exception {
        // 拿到message 要进行编码处理
        out.writeBytes(WenRpcConstants.MAGIC_NUMBER);
        out.writeByte(WenRpcConstants.VERSION);
        // 预留数据长度位置
        out.writerIndex(out.writerIndex() + 4);
        out.writeByte(wenMessage.getMessageType());
        // 序列化 先进行序列化 在进行压缩
        out.writeByte(wenMessage.getCodec());
        out.writeByte(wenMessage.getCompress());
        out.writeInt(ATOMIC_INTEGER.getAndIncrement());
        Object data = wenMessage.getData();
        // header 长度为 16
        int fullLength = WenRpcConstants.HEAD_LENGTH;
        // 序列化
        Serializer serializer = SPIUtils.getLoadSerializer(wenMessage.getCodec());
        byte[] bodyBytes = serializer.serialize(data);

        Compress compress = SPIUtils.getLoadCompress(wenMessage.getCompress());
        bodyBytes = compress.compress(bodyBytes);
        fullLength += bodyBytes.length;
        out.writeBytes(bodyBytes);
        int writerIndex = out.writerIndex();
        // 将fullLength写入之前的预留的位置
        out.writerIndex(writerIndex - fullLength + WenRpcConstants.MAGIC_NUMBER.length + 1);
        out.writeInt(fullLength);
        out.writerIndex(writerIndex);
    }
}
